/*
 * @Author: 2112778581 2112778581@qq.com
 * @Date: 2023-10-16 13:41:36
 * @LastEditors: fengshan525 2735332396@qq.com
 * @LastEditTime: 2025-09-21 16:51:45
 * @FilePath: \pra\src\list-detail\list-detail.service.ts
 * @Description: 列表详情服务
 */
import { Injectable, Inject, forwardRef } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { ListDetail } from '@libs/db/models/list-detail.model';
import { Category } from '@libs/db/models/category.model';
import { WebmenusService } from '../webmenus/webmenus.service';

@Injectable()
export class ListDetailService {
  constructor(
    @InjectModel('ListDetail') private readonly listDetailModel: Model<ListDetail>,
    @InjectModel('Category') private readonly categoryModel: Model<Category>,
    @Inject(forwardRef(() => WebmenusService))
    private readonly webmenusService: WebmenusService,
  ) { }

  /**
   * 创建列表详情
   * @param createListDetailDto 创建列表详情的数据传输对象
   * @returns 创建的列表详情对象
   */
  async create(createListDetailDto: Partial<ListDetail>): Promise<ListDetail> {
    const createdListDetail = new this.listDetailModel(createListDetailDto);
    return createdListDetail.save();
  }

  /**
   * 根据ID查找单个列表详情
   * @param id 列表详情ID
   * @returns 列表详情对象
   */
  async findOne(id: string): Promise<ListDetail> {
    return this.listDetailModel.findById(id).exec();
  }

  /**
   * 根据分类ID查找列表详情
   * @param categoryId 分类ID
   * @param pageNum 页码
   * @param pageSize 每页数量
   * @returns 查询结果
   */
  async findByCategory(
    categoryId: string,
    pageNum: number = 1,
    pageSize: number = 10
  ): Promise<{
    data: ListDetail[];
    total: number;
    pageNum: number;
    pageSize: number;
  }> {
    const skip = (pageNum - 1) * pageSize;

    const total = await this.listDetailModel.countDocuments({
      categoryId,
      isPublished: true
    });
    const data = await this.listDetailModel
      .find({ categoryId, isPublished: true })
      .skip(skip)
      .limit(pageSize)
      .sort({ createdAt: -1 });

    return {
      data,
      total,
      pageNum,
      pageSize,
    };
  }

  /**
   * 获取推荐列表详情
   * @param limit 限制数量
   * @returns 推荐列表详情数组
   */
  async findRecommended(limit: number = 10): Promise<ListDetail[]> {
    return this.listDetailModel
      .find({ isRecommend: true, isPublished: true })
      .limit(limit)
      .sort({ createdAt: -1 })
      .exec();
  }

  /**
   * 获取相关推荐列表详情
   * @param limit 限制数量
   * @returns 相关推荐列表详情数组
   */
  async findRelatedRecommended(limit: number = 10): Promise<ListDetail[]> {
    return this.listDetailModel
      .find({ isRelatedRecommend: true, isPublished: true })
      .limit(limit)
      .sort({ createdAt: -1 })
      .exec();
  }

  /**
   * 更新列表详情
   * @param id 列表详情ID
   * @param updateListDetailDto 更新数据
   * @returns 更新后的列表详情对象
   */
  async update(id: string, updateListDetailDto: Partial<ListDetail>): Promise<ListDetail> {
    return this.listDetailModel
      .findByIdAndUpdate(id, updateListDetailDto, { new: true })
      .exec();
  }

  /**
   * 增加浏览量
   * @param id 列表详情ID
   * @returns 更新结果
   */
  async incrementViewCount(id: string): Promise<ListDetail> {
    return this.listDetailModel
      .findByIdAndUpdate(id, { $inc: { viewCount: 1 } }, { new: true })
      .exec();
  }

  /**
   * 删除列表详情
   * @param id 列表详情ID
   * @returns 删除结果
   */
  async remove(id: string): Promise<ListDetail> {
    return this.listDetailModel.findByIdAndDelete(id).exec();
  }

  /**
   * 批量删除列表详情
   * @param ids 列表详情ID数组
   * @returns 删除结果
   */
  async removeMany(ids: string[]): Promise<any> {
    return this.listDetailModel.deleteMany({ _id: { $in: ids } }).exec();
  }

  /**
   * 获取下拉列表数据
   * @returns 下拉列表数据
   */
  async getDropdownList(): Promise<{ _id: string; title: string }[]> {
    return this.listDetailModel
      .find({ isPublished: true })
      .select('title _id')
      .sort({ createdAt: -1 })
      .exec();
  }

  /**
   * 根据标签查找列表详情
   * @param tagName 标签名称
   * @param pageNum 页码
   * @param pageSize 每页数量
   * @returns 查询结果
   */
  async findByTag(
    tagName: string,
    pageNum: number = 1,
    pageSize: number = 10
  ): Promise<{
    data: ListDetail[];
    total: number;
    pageNum: number;
    pageSize: number;
  }> {
    const skip = (pageNum - 1) * pageSize;

    const query = {
      'tags.name': tagName,
      isPublished: true
    };

    const total = await this.listDetailModel.countDocuments(query);
    const data = await this.listDetailModel
      .find(query)
      .populate('categoryId')
      .skip(skip)
      .limit(pageSize)
      .sort({ createdAt: -1 });

    return {
      data,
      total,
      pageNum,
      pageSize,
    };
  }

  /**
   * 根据复杂条件查询列表详情（从controller移动过来的方法）
   * @param body 查询参数
   * @returns 查询结果
   */
  async findAllWithFilters(body: any) {
    const { pageNum = 1, pageSize = 10, moduleId, categoryId, isPublished, isRecommend, title } = body;
    const skip = (pageNum - 1) * pageSize;

    // 构建查询条件
    const query: any = {};

    // 处理 categoryId，可能是父节点ID，需要获取所有子节点
    if (categoryId) {
      // 调用 webmenus 服务获取以 categoryId 为父节点的所有子节点
      const childMenus = await this.webmenusService.findByParentCode(categoryId);

      // 提取所有子节点的 code
      const childCodes = this.extractAllCodes(childMenus);

      // 如果有子节点，使用 $in 查询所有相关的 categoryId
      if (childCodes.length > 0) {
        // 包含父节点本身和所有子节点
        query.categoryId = { $in: [categoryId, ...childCodes] };
      } else {
        // 如果没有子节点，只查询父节点本身
        query.categoryId = categoryId;
      }
    }

    if (isPublished !== undefined) query.isPublished = isPublished;
    if (isRecommend !== undefined) query.isRecommend = isRecommend;
    if (moduleId) query.modelId = moduleId;
    if (title) query.title = { $regex: title, $options: 'i' };

    const total = await this.listDetailModel.countDocuments(query);
    const rows = await this.listDetailModel
      .find(query)
      .skip(skip)
      .limit(parseInt(pageSize))
      .sort({
        isTop: -1,
        isRecommend: -1,  // 优先显示推荐内容（true在前）
        sort: -1,
        viewCount: -1,    // 按访问量降序排列
        createdAt: -1     // 最后按创建时间降序排列 
      });

    return {
      rows,
      total,
    };
  }

  async findAllWithFiltersCount(body: any) {
    const { pageNum = 1, pageSize = 10, moduleId, categoryId, isPublished, isRecommend, title } = body;
    const skip = (pageNum - 1) * pageSize;

    // 构建查询条件
    const query: any = {};

    // 处理 categoryId，可能是父节点ID，需要获取所有子节点
    if (categoryId) {
      // 调用 webmenus 服务获取以 categoryId 为父节点的所有子节点
      const childMenus = await this.webmenusService.findByParentCode(categoryId);

      // 提取所有子节点的 code
      const childCodes = this.extractAllCodes(childMenus);

      // 如果有子节点，使用 $in 查询所有相关的 categoryId
      if (childCodes.length > 0) {
        // 包含父节点本身和所有子节点
        query.categoryId = { $in: [categoryId, ...childCodes] };
      } else {
        // 如果没有子节点，只查询父节点本身
        query.categoryId = categoryId;
      }
    }
    if (moduleId) query.modelId = moduleId;
    const total = await this.listDetailModel.countDocuments(query);
    return {
      total,
    };

  }

  /**
   * 根据复杂条件查询列表详情，优先根据是否推荐和访问量排序
   * @param body 查询参数（来源：用户输入）
   * @returns 查询结果
   */
  async findAllWithRecommendSort(body: any) {
    const { pageNum = 1, pageSize = 10, moduleId, categoryId, isPublished, isRecommend, title } = body;
    const skip = (pageNum - 1) * pageSize;

    // 构建查询条件
    const query: any = {};

    // 处理 categoryId，可能是父节点ID，需要获取所有子节点
    if (categoryId) {
      // 调用 webmenus 服务获取以 categoryId 为父节点的所有子节点
      const childMenus = await this.webmenusService.findByParentCode(categoryId);

      // 提取所有子节点的 code
      const childCodes = this.extractAllCodes(childMenus);

      // 如果有子节点，使用 $in 查询所有相关的 categoryId
      if (childCodes.length > 0) {
        // 包含父节点本身和所有子节点
        query.categoryId = { $in: [categoryId, ...childCodes] };
      } else {
        // 如果没有子节点，只查询父节点本身
        query.categoryId = categoryId;
      }
    }
    if (moduleId) query.modelId = moduleId;
    if (title) query.title = { $regex: title, $options: 'i' };
    query.isPublished = true;
    query.isRecommend = true;

    const total = await this.listDetailModel.countDocuments(query);
    const rows = await this.listDetailModel
      .find(query)
      .skip(skip)
      .limit(parseInt(pageSize))
      .sort({
        isTop: -1,
        isRecommend: -1,  // 优先显示推荐内容（true在前）
        sort: -1,
        viewCount: -1,    // 按访问量降序排列
        createdAt: -1     // 最后按创建时间降序排列
      });

    return {
      rows,
      total,
    };
  }

  /**
   * 递归提取所有菜单代码
   * @param menus 菜单数组
   * @returns 所有菜单代码数组
   */
  private extractAllCodes(menus: any[]): string[] {
    const codes: string[] = [];

    const extractCodes = (menuList: any[]) => {
      for (const menu of menuList) {
        if (menu.code) {
          codes.push(menu.code);
        }
        if (menu.children && menu.children.length > 0) {
          extractCodes(menu.children);
        }
      }
    };

    extractCodes(menus);
    return codes;
  }
}